#ifndef BSP_ARCH_ARMV8_AARCH64_PLATFORM_FT2004_H
#define BSP_ARCH_ARMV8_AARCH64_PLATFORM_FT2004_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "ft_types.h"

#define CORE0_AFF 0x0
#define CORE1_AFF 0x1
#define CORE2_AFF 0x100
#define CORE3_AFF 0x101

/*  Device register address */
#define FT_DEV_BASE_ADDR 0x28000000
#define FT_DEV_END_ADDR 0x2FFFFFFF

    /* PCI  */

#define FT_PCIE_NUM 1
#define FT_PCIE0_ID 0
#define FT_PCIE0_MISC_IRQ_NUM 59

#define FT_PCIE_CFG_MAX_NUM_OF_BUS 256
#define FT_PCIE_CFG_MAX_NUM_OF_DEV 32
#define FT_PCIE_CFG_MAX_NUM_OF_FUN 8

#define FT_PCI_CONFIG_BASEADDR 0x40000000
#define FT_PCI_CONFIG_REG_LENGTH 0x10000000

#define FT_PCI_IO_CONFIG_BASEADDR 0x50000000
#define FT_PCI_IO_CONFIG_REG_LENGTH 0x08000000

#define FT_PCI_MEM32_BASEADDR 0x58000000
#define FT_PCI_MEM32_REG_LENGTH 0x27ffffff

#define FT_PCI_MEM64_BASEADDR 0x1000000000
#define FT_PCI_MEM64_REG_LENGTH 0X1000000000

#define FT_PCI_EU0_C0_CONTROL_BASEADDR 0x29000000
#define FT_PCI_EU0_C1_CONTROL_BASEADDR 0x29010000
#define FT_PCI_EU0_C2_CONTROL_BASEADDR 0x29020000
#define FT_PCI_EU1_C0_CONTROL_BASEADDR 0x29030000
#define FT_PCI_EU1_C1_CONTROL_BASEADDR 0x29040000
#define FT_PCI_EU1_C2_CONTROL_BASEADDR 0x29050000

#define FT_PCI_EU0_CONFIG_BASEADDR 0x29100000
#define FT_PCI_EU1_CONFIG_BASEADDR 0x29101000

    // timer
#define GENERIC_TIMER_NS_IRQ_NUM 30
#define COUNTS_PER_SECOND GENERIC_TIMER_CLK_FREQ

    // UART

#define FT_UART_NUM 4
#define FT_UART_REG_LENGTH 0x18000

#define FT_UART0_ID 0
#define FT_UART0_IRQ_NUM 38
#define FT_UART0_BASE_ADDR 0x28000000
#define FT_UART0_CLK_FREQ_HZ 48000000

#define FT_UART1_ID 1
#define FT_UART1_IRQ_NUM 39
#define FT_UART1_BASE_ADDR 0x28001000
#define FT_UART1_CLK_FREQ_HZ 48000000

#define FT_UART2_ID 2
#define FT_UART2_IRQ_NUM 40
#define FT_UART2_BASE_ADDR 0x28002000
#define FT_UART2_CLK_FREQ_HZ 48000000

#define FT_UART3_BASE_ADDR 0x28003000
#define FT_UART3_ID 3
#define FT_UART3_IRQ_NUM 41
#define FT_UART3_CLK_FREQ_HZ 48000000

#define FT_STDOUT_BASE_ADDRESS FT_UART1_BASE_ADDR
#define FT_STDIN_BASE_ADDRESS FT_UART1_BASE_ADDR

/****** GIC v3  *****/
#define FT_GICV3_INSTANCES_NUM 1U
#define GICV3_REG_LENGTH 0x00009000

/*
 * The maximum priority value that can be used in the GIC.
 */
#define GICV3_MAX_INTR_PRIO_VAL 240U
#define GICV3_INTR_PRIO_MASK 0x000000f0U
#define ARM_GIC_IPI_COUNT 16 /* MPCore IPI count         */
#define SGI_INT_MAX 16
#define SPI_START_INT_NUM 32 /* SPI start at ID32        */
#define PPI_START_INT_NUM 16 /* PPI start at ID16        */
#define GIC_INT_MAX_NUM 1020 /* GIC max interrupts count */
#define GICV3_BASEADDRESS 0x29900000U
#define GICV3_DISTRIBUTOR_BASEADDRESS (GICV3_BASEADDRESS + 0)
#define GICV3_RD_BASEADDRESS (GICV3_BASEADDRESS + 0x80000U)
#define GICV3_RD_OFFSET (2U<<16)
#define FT_GICV3_VECTORTABLE_NUM GIC_INT_MAX_NUM

// gpio
#define GPIO0_BASE (0X28004000)
#define GPIO1_BASE (0X28005000)

#define F_GPIO_TOTAL_LINE (16)
#define F_GPIO_GROUP_NUM (2)

#define F_GPIO_PORT_MAX_NUM (2)
#define F_GPIO_PIN_MAX_NUM (16)

#define F_GPIO0_INTR_IRQ (42) // gpio0 irq number
#define F_GPIO1_INTR_IRQ (43) // gpio1 irq number

// spi
#define FSPI0_BASE 0x2800c000
#define FSPI1_BASE 0x28013000
#define FSPI_FREQ 48000000
#define FSPI_DEVICE_NUM 2
#define FSPI0_IRQ_NUM 50
#define FSPI1_IRQ_NUM 51
#define FSPI0_IOMUX_CSN0_OFFSET 19
#define FSPI0_IOMUX_SCK_OFFSET 20
#define FSPI0_IOMUX_SO_OFFSET 21
#define FSPI0_IOMUX_SI_OFFSET 22

/* QSPI */
#define QSPI_NUM 1U
#define QSPI_INSTANCE 0
#define QSPI_MAX_CS_NUM 4
#define QSPI_BASEADDR 0x28014000
#define QSPI_MEM_START_ADDR 0x0
#define QSPI_MEM_END_ADDR 0x1FFFFFFF

// iomux
#define FIOMUX_REG_BASEADDR 0x28180200
#define FIOMUX_REG_LENGTH (12)
#define FIOMUX_REG_TYPE u32

#define IOMUX_ALL_PLL_LOCK_PAD (0)
#define IOMUX_CRU_CLK_OBV_PAD (1)
#define IOMUX_SJTAG_TDI_PAD (2)
#define IOMUX_SJTAG_TMS_PAD (3)
#define IOMUX_SJTAG_NTRST_PAD (4)
#define IOMUX_SJTAG_TDO_PAD (5)
#define IOMUX_TJTAG_TDO_PAD (6)
#define IOMUX_TJTAG_NTRST_PAD (7)
#define IOMUX_TJTAG_TMS_PAD (8)
#define IOMUX_TJTAG_TDI_PAD (9)
#define IOMUX_NTRST_SWJ_PAD (10)
#define IOMUX_TDI_SWJ_PAD (11)
#define IOMUX_SWDITMS_SWJ_PAD (12)
#define IOMUX_SWDO_SWJ_PAD (13)
#define IOMUX_TDO_SWJ_PAD (14)
#define IOMUX_HDT_MB_DONE_STATE_PAD (15)
#define IOMUX_HDT_MB_FAIL_STATE_PAD (16)
#define IOMUX_I2C_0_SCL_PAD (17)
#define IOMUX_I2C_0_SDA_PAD (18)
#define IOMUX_SPI0_CSN0_PAD (19)
#define IOMUX_SPI0_SCK_PAD (20)
#define IOMUX_SPI0_SO_PAD (21)
#define IOMUX_SPI0_SI_PAD (22)
#define IOMUX_SD_CMD_PAD (23)
#define IOMUX_SD_CLK_PAD (24)
#define IOMUX_SD_DAT0_PAD (25)
#define IOMUX_SD_DAT1_PAD (26)
#define IOMUX_SD_DAT2_PAD (27)
#define IOMUX_SD_DAT3_PAD (28)
#define IOMUX_SD_DETECT_PAD (29)
#define IOMUX_HDA_BCLK_PAD (30)
#define IOMUX_HDA_RST_PAD (31)
#define IOMUX_HDA_SYNC_PAD (32)
#define IOMUX_HDA_SDO_PAD (33)
#define IOMUX_HDA_SDI0_PAD (34)
#define IOMUX_UART_0_RXD_PAD (35)
#define IOMUX_UART_0_TXD_PAD (36)
#define IOMUX_UART_1_RXD_PAD (37)
#define IOMUX_UART_1_TXD_PAD (38)
#define IOMUX_UART_2_RXD_PAD (39)
#define IOMUX_UART_2_TXD_PAD (40)
#define IOMUX_UART_3_RXD_PAD (41)
#define IOMUX_UART_3_TXD_PAD (42)
#define IOMUX_QSPI_CSN0_PAD (43)
#define IOMUX_QSPI_CSN1_PAD (44)
#define IOMUX_QSPI_CSN2_PAD (45)
#define IOMUX_QSPI_CSN3_PAD (46)
#define IOMUX_QSPI_SCK_PAD (47)
#define IOMUX_QSPI_SO_IO0_PAD (48)
#define IOMUX_QSPI_SI_IO1_PAD (49)
#define IOMUX_QSPI_WP_IO2_PAD (50)
#define IOMUX_QSPI_HOLD_IO3_PAD (51)
#define IOMUX_EXT_LPC_LAD_0_PAD (52)
#define IOMUX_EXT_LPC_LAD_1_PAD (53)
#define IOMUX_EXT_LPC_LAD_2_PAD (54)
#define IOMUX_EXT_LPC_LAD_3_PAD (55)
#define IOMUX_PEU0_LINKUP0_PAD (56)
#define IOMUX_PEU0_LINKUP1_PAD (57)
#define IOMUX_PEU0_LINKUP2_PAD (58)
#define IOMUX_PEU0_C0_CLKREQ_PAD (59)
#define IOMUX_PEU0_C1_CLKREQ_PAD (60)
#define IOMUX_PEU0_C2_CLKREQ_PAD (61)
#define IOMUX_PEU1_C0_CLKREQ_PAD (62)
#define IOMUX_PEU1_C1_CLKREQ_PAD (63)
#define IOMUX_PEU1_C2_CLKREQ_PAD (64)
#define IOMUX_PHY_GMAC0_CLK_RX_PAD (65)
#define IOMUX_GMAC0_PHY_CLK_TX_PAD (66)
#define IOMUX_PHY_GMAC0_RXD0_PAD (67)
#define IOMUX_PHY_GMAC0_RXD1_PAD (68)
#define IOMUX_PHY_GMAC0_RXD2_PAD (69)
#define IOMUX_PHY_GMAC0_RXD3_PAD (70)
#define IOMUX_PHY_GMAC0_RXDV_PAD (71)
#define IOMUX_GMAC0_PHY_TXD0_PAD (72)
#define IOMUX_GMAC0_PHY_TXD1_PAD (73)
#define IOMUX_GMAC0_PHY_TXD2_PAD (74)
#define IOMUX_GMAC0_PHY_TXD3_PAD (75)
#define IOMUX_GMAC0_PHY_TXEN_PAD (76)
#define IOMUX_GMAC0_PHY_MDC_PAD (77)
#define IOMUX_GMAC0_PHY_MDIO_PAD (78)
#define IOMUX_PHY_GMAC1_CLK_RX_PAD (79)
#define IOMUX_GMAC1_PHY_CLK_TX_PAD (80)
#define IOMUX_CKOBV_SEL0_PAD (81)
#define IOMUX_CKOBV_SEL1_PAD (82)
#define IOMUX_CKOBV_SEL2_PAD (83)
#define IOMUX_CKOBV_SEL3_PAD (84)
#define IOMUX_CKOBV_SEL4_PAD (85)
#define IOMUX_GMAC1_PHY_TXD0_PAD (86)
#define IOMUX_GMAC1_PHY_TXD1_PAD (87)
#define IOMUX_RESERVED1 (88)
#define IOMUX_RESERVED2 (89)
#define IOMUX_GMAC1_PHY_TXD2_PAD (90)
#define IOMUX_GMAC1_PHY_TXD3_PAD (91)
#define IOMUX_GMAC1_PHY_TXEN_PAD (92)
#define IOMUX_GMAC1_PHY_MDC_PAD (93)
#define IOMUX_GMAC1_PHY_MDIO_PAD (94)
#define IOMUX_RESERVED3 (95)
#define IOMUX_PAD_NUM (96)

// Gic
#define ARM_GIC_NR_IRQS 1024
#define ARM_GIC_IRQ_START 0

// can
#define FCAN_REF_CLOCK 600000000

#define FCAN_ARB_TSEG1_MIN 1
#define FCAN_ARB_TSEG1_MAX 8
#define FCAN_ARB_TSEG2_MIN 1
#define FCAN_ARB_TSEG2_MAX 8
#define FCAN_ARB_SJW_MAX 4
#define FCAN_ARB_BRP_MIN 1
#define FCAN_ARB_BRP_MAX 512
#define FCAN_ARB_BRP_INC 1

#define FCAN_DATA_TSEG1_MIN 1
#define FCAN_DATA_TSEG1_MAX 8
#define FCAN_DATA_TSEG2_MIN 1
#define FCAN_DATA_TSEG2_MAX 8
#define FCAN_DATA_SJW_MAX 4
#define FCAN_DATA_BRP_MIN 1
#define FCAN_DATA_BRP_MAX 512
#define FCAN_DATA_BRP_INC 1

#define FT_CAN_USE_CANFD 0

#define FT_CAN_NUM 3
#define FT_CAN_REG_LENGTH 0x1000
#define FT_CAN0_BASEADDR 0x28207000
#define FT_CAN1_BASEADDR 0x28207400
#define FT_CAN2_BASEADDR 0x28207800
#define FT_CAN0_IRQNUM 119
#define FT_CAN1_IRQNUM 123
#define FT_CAN2_IRQNUM 124

#define FT_CAN0_INSTANCE_ID 0
#define FT_CAN1_INSTANCE_ID 1
#define FT_CAN2_INSTANCE_ID 2

#define FCAN_IOMUX_CAN0_TX_OFFSET 9
#define FCAN_IOMUX_CAN0_RX_OFFSET 12
#define FCAN_IOMUX_CAN1_TX_OFFSET 10
#define FCAN_IOMUX_CAN1_RX_OFFSET 13
#define FCAN_IOMUX_CAN2_TX_OFFSET 11
#define FCAN_IOMUX_CAN2_RX_OFFSET 15

    /* I2C */
    typedef enum
    {
        I2C_INSTANCE_0 = 0,
        I2C_INSTANCE_1,
        I2C_INSTANCE_2,
        I2C_INSTANCE_3,
        I2C_INSTANCE_NUM
    } I2cInstance;

#define I2C_0_BASEADDR 0x28006000
#define I2C_1_BASEADDR 0x28007000
#define I2C_2_BASEADDR 0x28008000
#define I2C_3_BASEADDR 0x28009000

#define I2C_0_INTR_IRQ 44
#define I2C_1_INTR_IRQ 45
#define I2C_2_INTR_IRQ 46
#define I2C_3_INTR_IRQ 47

#define I2C_REF_CLK_HZ 48000000 /* 48MHz */

/* WDT */
    typedef enum
    {
        WDT_INSTANCE_0 = 0,
        WDT_INSTANCE_1,
    
        WDT_INSTANCE_NUM
    } WdtInstance;

#define WDT0_REFRESH_BASE 0x2800a000
#define WDT0_CONTROL_BASE 0x2800b000
#define WDT1_REFRESH_BASE 0x28016000
#define WDT1_CONTROL_BASE 0x28017000

#define WDT0_INTR_IRQ 48
#define WDT1_INTR_IRQ 49

#define WDT_CLK 48000000 /* 48MHz */

    /* SDCI */
    typedef enum
    {
        FSDMMC_HOST_INSTANCE_0 = 0,
        FSDMMC_HOST_INSTANCE_NUM
    } SdciHostInstance;

#define FSDMMC_HOST_0_BASEADDR 0x28207C00

#define FSDMMC_HOST_0_DMA_INTR_IRQ 52
#define FSDMMC_HOST_0_CMD_INTR_IRQ 53
#define FSDMMC_HOST_0_ERR_INTR_IRQ 54

#define FSDMMC_CLK_FREQ_HZ 600000000 /* 600 MHz */
#define SDCI_SEN_DEBNCE 10000000   /* 10 MHz */
#define SDCI_CMD_TIMEOUT 10000000  /* 1s */
#define SDCI_DATA_TIMEOUT 40000000 /* 4S */

/* GMAC */
#define GMAC_PUB_REG_BASE_ADDR      0x2820B000  /* 公共寄存器基地址 */

enum
{
    GMAC_INSTANCE_0 = 0,
    GMAC_INSTANCE_1,

    GMAC_INSTANCE_NUM
};

#define GMAC_INSTANCE_0_BASE_ADDR   0x2820C000
#define GMAC_INSTANCE_1_BASE_ADDR   0x28210000

#define GMAC_INSTANC_0_IRQ          81
#define GMAC_INSTANC_1_IRQ          82

#define GMAC_DMA_MIN_ALIGN          128
#define GMAC_MAX_PACKET_SIZE        1600

#define FT_CPUS_NR 4

#ifdef __cplusplus
}
#endif

#endif // !